package net.lab1024.sa.admin.module.business.aps.domain.optaplanner;

import lombok.Data;
import lombok.NoArgsConstructor;

import java.time.LocalDateTime;
import java.util.List;

/**
 * OptaPlanner资源实体
 * 用于APS排程优化的资源定义
 *
 * @Author 1024创新实验室
 * @Date 2025-01-28
 * @Wechat zhuoda1024
 * @Email lab1024@163.com
 * @Copyright <a href="https://1024lab.net">1024创新实验室</a>
 */
@Data
@NoArgsConstructor
public class Resource {

    /**
     * 资源ID
     */
    private Long resourceId;

    /**
     * 资源名称
     */
    private String resourceName;

    /**
     * 资源类型
     */
    private String resourceType;

    /**
     * 资源描述
     */
    private String description;

    /**
     * 资源容量（同时处理任务数量）
     */
    private Integer capacity;

    /**
     * 工作开始时间
     */
    private LocalDateTime workStartTime;

    /**
     * 工作结束时间
     */
    private LocalDateTime workEndTime;

    /**
     * 是否可用
     */
    private Boolean available;

    /**
     * 效率系数（0.1-2.0，1.0为标准效率）
     */
    private Double efficiencyFactor;

    /**
     * 维护时间段列表
     */
    private List<MaintenanceWindow> maintenanceWindows;

    /**
     * 构造函数
     */
    public Resource(Long resourceId, String resourceName, String resourceType, 
                   String description, Integer capacity, LocalDateTime workStartTime, 
                   LocalDateTime workEndTime, Boolean available, Double efficiencyFactor) {
        this.resourceId = resourceId;
        this.resourceName = resourceName;
        this.resourceType = resourceType;
        this.description = description;
        this.capacity = capacity;
        this.workStartTime = workStartTime;
        this.workEndTime = workEndTime;
        this.available = available;
        this.efficiencyFactor = efficiencyFactor;
    }

    /**
     * 检查资源在指定时间是否可用
     */
    public boolean isAvailableAt(LocalDateTime startTime, LocalDateTime endTime) {
        if (!available) {
            return false;
        }
        
        // 检查工作时间
        if (startTime.isBefore(workStartTime) || endTime.isAfter(workEndTime)) {
            return false;
        }
        
        // 检查维护时间
        if (maintenanceWindows != null) {
            for (MaintenanceWindow window : maintenanceWindows) {
                if (window.isOverlapping(startTime, endTime)) {
                    return false;
                }
            }
        }
        
        return true;
    }

    /**
     * 计算实际任务持续时间（考虑效率系数）
     */
    public Integer calculateActualDuration(Integer baseDuration) {
        if (efficiencyFactor == null || efficiencyFactor <= 0) {
            return baseDuration;
        }
        return (int) Math.ceil(baseDuration / efficiencyFactor);
    }

    /**
     * 维护时间窗口内部类
     */
    @Data
    @NoArgsConstructor
    public static class MaintenanceWindow {
        private LocalDateTime startTime;
        private LocalDateTime endTime;
        private String description;

        public MaintenanceWindow(LocalDateTime startTime, LocalDateTime endTime, String description) {
            this.startTime = startTime;
            this.endTime = endTime;
            this.description = description;
        }

        /**
         * 检查是否与指定时间段重叠
         */
        public boolean isOverlapping(LocalDateTime checkStart, LocalDateTime checkEnd) {
            return !(checkEnd.isBefore(startTime) || checkStart.isAfter(endTime));
        }
    }
}